/*
 * op_guninfo.cpp
 *
 *  Created on: 2019-8-16
 *      Author: ltp
 */

#include "database.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "codetable.h"
#include "ret.h"

Gun_Info gun;

typedef enum{
	TABLE_YX,
	TABLE_STOPREASON,
}TypeTable;

void help(){
	char* help =
			"[##  功能选项  四选一  ##]\n"
			"-guninfo\t\t\t:操作枪信息  例子: ./exefile -guninfo\n"
			"-yxcode\t\t\t\t:操作遥信编码表   例子:./exefile -yxcode\n"
			"-stopcode\t\t\t:操作停止原因编码表   例子:./exefile -stopcode\n"
			"-h, --help\t\t\t: 查看操作方法,并退出.   例子: ./exefile  -h\n\n"

			"[##  -guninfo 操作枪信息配置说明  ##]\n"
			"[$option 操作选项]:\n"
			"-l, --list\t\t\t:查看所有枪的配置信息.   例子: ./exefile  -guninfo -l\n"
			"-d, --delete  [gunno]\t\t:删除某把枪的配置信息,gunno是枪号.   例子: ./exefile -guninfo -d  gunno=0\n"
			"-u, --update [para...]\t\t:插入或更新枪的信息,参数中必须包含gunno. 例子./exefile -guninfo -u gunno=1  can_port=1 "
			"frame_gunno=1 cha_addr=246 mt_port=1 phase_num=1 meteraddr=112233445566 ct=1\n"
			"[$para 参数选项]:\n"
			"gunno\t\t\t\t:枪号,第一把枪从0开始编码.十进制		 例子: gunno=0 \n"
			"can_port\t\t\t:枪所接入的can接口编码0(can0)或1(can1).十进制		例子: can_port=0 \n"
			"frame_gunno\t\t\t:控制器can报文里面的枪口标示 .	十进制	例子: frame_gunno=0\n"
			"cha_addr\t\t\t:控制器的can地址,	十进制  例子:cha_addr=246\n"
			"mt_port\t\t\t\t:充电枪电表接的485接口,从1开始.十进制		例子:mt_port=1\n"
			"phase_num\t\t\t:表的相数，1单相表  3三相表. 十进制   例子:phase_num=1\n"
			"meteraddr\t\t\t:电表地址,长度12. 十进制     例子:meteraddr=00112233445566\n"
			"ct\t\t\t\t:互感器变比. 十进制  例子:ct=1\n\n"

			"[##  -yxcode 操作遥信编码表配置说明  ##]\n"
			"[$option  操作选项]:\n"
			"-l, --list\t\t\t:查看收录的遥信编码配置信息.   例子: ./exefile -yxcode -l\n"
			"-v, --view [swcode]\t\t\t:查看某个遥信编码的配置信息. 例子:./exefile -yxcode -v swcode=1\n"
			"-d, --delete  [swcode]\t\t:删除某个遥信编码的配置信息,swcode具体的昇伟编码点位.  例子: ./exefile -yxcode -d  swcode=0\n"
			"-u, --update [para...]\t\t:插入或更新某个遥信编码的信息,参数中必须包含swcode和xjcode ./exefile -yxcode -u  swcode=0 xjcode=0\n"
			"[$para 参数选项]:\n"
			"swcode\t\t\t\t:昇伟遥信编码 例子：swcode=13\n"
			"xjcode\t\t\t\t:小桔状态编码  例子：xjcode=501A\n\n"

			"[##  -stopcode 操作停止原因编码表配置说明  ##]\n"
			"[$option  操作选项]:\n"
			"-l, --list\t\t\t:查看收录的停止原因编码表配置信息.   例子: ./exefile -stopcode -l\n"
			"-v, --view [swcode]\t\t\t:查看某个停止原因的编码信息. 例子: ./exefile -stopcode -v swcode=101\n"
			"-d, --delete  [swcode]\t\t:删除某个停止原因的配置信息,swcode具体的昇伟编码点位.  例子: ./exefile -stopcode -d  swcode=0\n"
			"-u, --update [para...]\t\t:插入或更新某个停止原因编码的信息,参数中必须包含swcode和xjcode ./exefile -stopcode -u  swcode=0 xjcode=0\n"
			"[$para 参数选项]:\n"
			"swcode\t\t\t\t:昇伟遥信编码 例子：swcode=205\n"
			"xjcode\t\t\t\t:小桔状态编码  例子：xjcode=301B\n\n"
			;

	printf("Usage: ./set_guninfo -guninfo |-yxcode |-stopcode| -h [$option]  [$para...]\n");
	printf("%s\n",help);
}

int  get_operate(int argc, char *argv[]){
	int i=0;

	if(argc < 3){
		return -1;
	}

	if(strcmp(argv[2],"-l")==0  || strcmp(argv[2],"--list")==0){
		if(argc!=3){
			return -1;
		}
		return 1;
	}
	else if(strcmp(argv[2],"-d")==0  || strcmp(argv[2],"--delete")==0){
		if (argc != 4){
			return -1;
		}
		return 2;
	}
	else if(strcmp(argv[2],"-u")==0  || strcmp(argv[2],"--update")==0){
		if (argc < 4){
			return -1;
		}
		return 3;
	}
	else if(strcmp(argv[2],"-v")==0  || strcmp(argv[2],"--view")==0){
		if (argc != 4){
			return -1;
		}
		return 4;
	}

	return 0;
}

void  list_guninfo()
{
	Gun_Info gun;
	int ret=0, i=0, j=0;
	unsigned char gunno = 0;
	int flag = 1;

	for(i=0; i<30; i++){
		memset(&gun,0,sizeof(gun));
		ret = protocol_get_GunInfo(gunno, &gun);        
		if(flag){
			printf("gunno\tcan_port\tframe_gunno\tcha_addr\tmt_port\tphase_num\tct\tmeteraddr\n");
			flag=0;
		}
		if(ret == 0){
			printf("%02d\t%02d\t\t0x%02x\t\t0x%02x\t\t%02d\t%d\t\t%d\t",gun.gunno,gun.can_port,gun.frame_gunno,
					gun.cha_addr,gun.mt_port,gun.phase_num,gun.ct);
			for(j=0; j<6; j++)
				printf("%02x",gun.meteraddr[j]);
			printf("\n");
		}
		else if(ret!=0 && i>=8)
			break;

		gunno++;
	}
}

void delete_guninfo(char* argv[]){
	int ret = 0;
	int gunno = 0;
	char* p = NULL;

	if(strncmp(argv[3],"gunno=",6) == 0){
		p = strchr(argv[3],'=');
		p += 1;
		gunno = atoi(p);
		protocol_delete_GunInfo(gunno);
	}
	else
		help();
}

int string_to_hex_array(unsigned char* dst, char* src)
{
	long long dec = 0;
	int i = 0, len=0, j=0;
	int tmp = 0;
	int m_len = 0;

	len=strlen(src);
	dec = atoll(src);

	if(len%2 == 0)
		m_len = len/2;
	else
		m_len = len/2 + 1;

	unsigned char *m_src = (unsigned char*)malloc(sizeof(char)*m_len);

	for(i=0; i<len; ){
		tmp = dec%10;
		m_src[j]= tmp;
		dec = dec/10;

		tmp = dec%10;
		m_src[j] |= tmp<<4;
		dec = dec/10;
		j++;
		i += 2;
	}

	for(i=0; i<m_len; i++)
		dst[i] = m_src[m_len-1-i];

	free(m_src);
	return 0;
}


void update_guninfo(int argc, char* argv[]){
	Gun_Info gunDb;
	int i=0;
	char* p = NULL;
	int gunno = 0;
	int flag = 1, flag1=0;
	int length = 0, index=0;

	memset(&gunDb,0,sizeof(Gun_Info));

	for(i=3; i<argc; i++){
		p = strchr(argv[i],'=');
		if(p!=NULL){
			length = p - &argv[i][0] + 1;
			p+=1;
			if(strncmp(argv[i],"gunno=",length) == 0){
				gunno = atoi(p);
				protocol_get_GunInfo(gunno,&gunDb);
				break;
			}
		}
	}

	if(i >= argc){
		printf("missing  gunno para !!!\n");
		help();
		return;
	}

	for(i=3; i<argc; i++){
		p = strchr(argv[i],'=');
		if(p == NULL){
			printf("%s is error !!!\n",argv[i]);
			break;
		}
		length = p - &argv[i][0] + 1;
		p+=1;
		if(strncmp(argv[i],"gunno=",length) == 0){
			gunDb.gunno =  atoi(p);
			continue;
		}
		else if(strncmp(argv[i],"can_port=",length) == 0){
			gunDb.can_port = atoi(p);
			flag1=1;
		}
		else if(strncmp(argv[i],"frame_gunno=",length) == 0){
			gunDb.frame_gunno =atoi(p);
			flag1=1;
		}
		else if(strncmp(argv[i],"cha_addr=",length) == 0){
			gunDb.cha_addr = atoi(p);
			flag1=1;
		}
		else if(strncmp(argv[i],"mt_port=",length) == 0){
			gunDb.mt_port = atoi(p);
			flag1=1;
		}
		else if(strncmp(argv[i],"phase_num=",length) == 0){
			gunDb.phase_num = atoi(p);
			flag1=1;
		}
		else if(strncmp(argv[i],"meteraddr=",length) == 0){
			if(strlen(argv[i]) != length+12){
				printf("meteraddr length is error!\n");
				return;
			}
			string_to_hex_array(gunDb.meteraddr, p);
			flag1=1;
		}
		else if(strncmp(argv[i],"ct=",length) == 0){
			gunDb.ct = atoi(p);
			flag1=1;
		}
		else{
			flag = 0;
			printf("%s is error, no exist this para!\n",argv[i]);
			break;
		}

	}

	if(flag && flag1){
		protocol_update_GunInfo(&gunDb);
	}
	else
		help();
}

int get_function(int argc, char* argv[])
{
	int ret = -1;
	if(argc<2){
		return ret;
	}

	if(strcmp(argv[1],"-guninfo") == 0){
		ret = 1;
	}
	else if(strcmp(argv[1],"-yxcode") == 0){
		ret=2;
	}
	else if(strcmp(argv[1],"-stopcode") == 0){
		ret=3;
	}
	else if(strcmp(argv[1],"-h") == 0 || strcmp(argv[1],"--help")==0){
		ret=4;
	}

	return ret;
}

void switch_guninfo(int argc, char* argv[])
{
	int ret = 0;
	ret = get_operate(argc, argv);
	switch(ret){
	case 1:
		list_guninfo();
		break;
	case 2:
		delete_guninfo(argv);
		break;
	case 3:
		update_guninfo(argc,argv);
		break;
	default:
		help();
	}

}

int list_code(int type)
{
	int ret = 0;
	int i = 0;
	Display_Code code;

	printf("%-72s\t%s\t\t%s\n\n","context","sw_code","xj_code");
	if(type == TABLE_YX){
		while(strcmp(Table_YX[i].context,"NULL")){
			memset(&code,0,sizeof(Display_Code));
			if(protocol_get_YxCode(Table_YX[i].sw_code,&code) == ERROR_OK )
				printf("%-72s\t%d\t\t%X\n",code.context,code.sw_code,code.xj_code);
			i++;
		}
	}else if(type == TABLE_STOPREASON){
		while(strcmp(Table_StopReason[i].context,"NULL")){
			memset(&code,0,sizeof(Display_Code));
			if(protocol_get_StopReasonCode(Table_StopReason[i].sw_code,&code) == ERROR_OK )
				printf("%-72s\t%d\t\t%X\n",code.context,code.sw_code,code.xj_code);
			i++;
		}
	}

	return 0;
}

int view_code(int type, int argc, char* argv[])
{
	Display_Code code;
	char *p=NULL;
	int swcode = 0;

	if(strncmp(argv[3],"swcode=",7) == 0){
		p = strchr(argv[3],'=');
		p += 1;
		swcode = atoi(p);
		if(type == TABLE_YX){
			if(protocol_get_YxCode(swcode,&code) == ERROR_OK){
				printf("%-72s\t%s\t\t%s\n\n","context","sw_code","xj_code");
				printf("%-72s\t%d\t\t%X\n",code.context,code.sw_code,code.xj_code);
			}
		}else if(type == TABLE_STOPREASON){
			if(protocol_get_StopReasonCode(swcode,&code) == ERROR_OK){
				printf("%-72s\t%s\t\t%s\n","context","sw_code","xj_code");
				printf("%-72s\t%d\t\t%X\n",code.context,code.sw_code,code.xj_code);
			}
		}
	}
	else
		help();

	return 0;
}

int delete_code(int type, char* argv[])
{
	Display_Code code;
	char *p=NULL;
	int swcode = 0;

	if(strncmp(argv[3],"swcode=",7) == 0){
		p = strchr(argv[3],'=');
		p += 1;
		swcode = atoi(p);
		if(type == TABLE_YX)
			protocol_delete_YxCode(swcode);
		else if(type == TABLE_STOPREASON)
			protocol_delete_StopReasonCode(swcode);
	}
	else
		help();

	return 0;
}

static char ctoh(const char ch) {
	if (ch >= '0' && ch <= '9')
		return (unsigned char) atoi(&ch);
	else if (ch >= 'A' && ch <= 'F')
		return (0xa + (ch - 'A'));
	else if (ch >= 'a' && ch <= 'f')
		return (0xa + (ch - 'a'));
	else
		printf("ctoh fail !!!----ch=%c\n", ch);
	return 0;
}

static int stoh(char* str)
{
	int len = 0;
	int i = 0;
	int hex = 0,tmp = 0;

	len = strlen(str);
	for(i=0; i<len; i++){
		tmp = ctoh(str[i]);
		hex |= (tmp<<(4*(len-i-1)));
	}

	return hex;
}

int update_code(int type, int argc, char* argv[])
{
	Display_Code code;
	char *p=NULL;
	int swcode = 0;
	int i = 0;
	int flag = 0;

	for(i=3; i<5; i++){
		if(strncmp(argv[i],"swcode=",7) == 0){
			p = strchr(argv[i],'=');
			p += 1;
			code.sw_code = atoi(p);

		}
		else if(strncmp(argv[i],"xjcode=",7) == 0){
			p = strchr(argv[i],'=');
			p += 1;
			code.xj_code = stoh(p);
			printf("xjcode=%d\n",code.xj_code);
		}
		else{
			help();
			flag = 1;
		}
	}

	if(!flag){
		if(type==TABLE_YX)
			protocol_update_YxCode(&code);
		else if(type == TABLE_STOPREASON)
			protocol_update_StopReasonCode(&code);
	}

	return 0;
}

void switch_yxcode(int argc, char* argv[])
{
	int ret = 0;

	ret = get_operate(argc, argv);
	switch(ret){
	case 1:
		list_code(TABLE_YX);
		break;
	case 2:
		delete_code(TABLE_YX,argv);
		break;
	case 3:
		update_code(TABLE_YX,argc,argv);
		break;
	case 4:
		view_code(TABLE_YX,argc,argv);
		break;
	default:
		help();
	}
}

void switch_stopreason_code(int argc, char* argv[])
{
	int ret = 0;

	ret = get_operate(argc, argv);
	switch(ret){
	case 1:
		list_code(TABLE_STOPREASON);
		break;
	case 2:
		delete_code(TABLE_STOPREASON,argv);
		break;
	case 3:
		update_code(TABLE_STOPREASON,argc,argv);
		break;
	case 4:
		view_code(TABLE_STOPREASON,argc,argv);
		break;
	default:
		help();
	}
}

int main(int argc, char *argv[])
{
	int ret = 0;

	ret = get_function(argc,argv);
	switch(ret){
	case 1:
		switch_guninfo(argc,argv);
		break;
	case 2:
		switch_yxcode(argc,argv);
		break;
	case 3:
		switch_stopreason_code(argc,argv);
		break;
	case 4:
		help();
		break;
	default:
		help();
	}




	return 0;
}


